import os
import json
from neo4j import GraphDatabase
import re


sdp_uri = "neo4j://211.71.15.39:10687"
self_uri = "neo4j://localhost:7687"
# 用户名密码
sdp_username = "neo4j"
sdp_password = "linux"

# 软件包之间可能的9种关系
dependencies = ['Depends', 'Pre-Depends', 'Recommends', 'Suggests',
                'Enhances', 'Breaks', 'Conflicts', 'Replaces', 'Provides']
global_all_ops = {}
global_all_keys = {}
contrs = []


def connect_database(uri=sdp_uri, db_username=sdp_username, db_password=sdp_password):
    driver = GraphDatabase.driver(uri, auth=(db_username, db_password),
                                  max_connection_lifetime=3600 * 24 * 30, keep_alive=True)
    return driver


# 获取条目信息，没有条目则返回""
def get_value(package_dict, key_str):
    try:
        return package_dict[key_str]
    except BaseException:
        return ""



def generate_query():
    with open("./assignment_file.txt", "r", encoding="utf-8") as fp:
        assignment_lists = fp.readlines()
        for assignment_str in assignment_lists:
            assignment_list = assignment_str.replace("')", "").replace(" ", "").replace("\n", "").split("=get_value(package_dict,'")
            if len(assignment_list) < 2:
                continue
            # print(assignment_list[1] + ": $" + assignment_list[0], end=", ")
            print(assignment_list[0] + "=" + assignment_list[0], end=", ")


# 检测约束()内是否都只有一个约束条件---> xenial的检测结果是的
# 计数有多少个约束()数，和所有前有(的符号总和比对，发现确实相同
def detect_constraint_nums(package_dict, nums):  # 看看都用到了哪些符号
    for rela in dependencies:
        rela_str = get_value(package_dict, rela)
        if rela == "":  # 先排除掉不存在的依赖关系
            continue
        match_constrs_list = re.findall(r'\(.*? .*?\)', rela_str)
        if match_constrs_list is None:
            continue
        nums += len(match_constrs_list)
    return nums


# 看看都用到了哪些符号
def get_vers_constraint_ops(package_dict):
    for rela in dependencies:
        rela_str = get_value(package_dict, rela)
        if rela == "":  # 先排除掉不存在的依赖关系
            continue
        rela_list = re.split('[\,\|]', rela_str)
        for pkg_dep in rela_list:
            match_op = re.search(r'\(.*? ', pkg_dep)
            if match_op is None:
                continue
            op = match_op.group()[1:-1]
            if op in global_all_ops:
                global_all_ops[op] = global_all_ops[op] + 1
            else:
                global_all_ops[op] = 1


# 搜索元数据包含的所有关键字及关键字出现次数（每次搜索一个文件，加入global_all_keys中）
def find_all_keys(package_dict):
    for key, _ in package_dict.items():
        if key in global_all_keys:
            global_all_keys[key] = global_all_keys[key] + 1
        else:
            global_all_keys[key] = 1



global_rela_count = {'Depends':0, 'Pre-Depends':0, 'Recommends':0, 'Suggests':0,
                'Enhances':0, 'Breaks':0, 'Conflicts':0, 'Replaces':0, 'Provides':0}
# 数数总共有多少条关系
def rela_count(package_dict):
    for rela in dependencies:
        rela_str = get_value(package_dict, rela)
        if rela_str == "":  # 先排除掉不存在的依赖关系
            continue
        # 分析依赖，形成字典形式
        # 先根据','分解
        this_count = 0
        depend_item_list = rela_str.split(',')  # 这里每项中可能会有'[] | []'这种并列形式
        for depend_item in depend_item_list:  # 本体软件包必须依赖每个item，但这层关系该怎么表示呢？目前想到的的方法是在关系上做文章
            depend_pkg_list = depend_item.strip().split(' | ')
            this_count += len(depend_pkg_list)
        global_rela_count[rela_str] += this_count


# 遍历所有json文件
def ergodic_json_files(func): # func是遍历时要执行的操作
    json_names = []
    for _, _, fs in os.walk("./xenial"):
        json_names = fs

    # contraint_nums = 0

    for json_name in json_names:
        if not json_name.__contains__(".json"):  # 排除掉中间文件和gz文件
            continue
        with open("./xenial/" + json_name, 'r', encoding='utf8')as fp:
            packages_store_dict = json.load(fp)
            for key, package_dict in packages_store_dict.items():
                pass
                # contraint_nums = detect_constraint_nums(package_dict, contraint_nums)
                # get_vers_constraint_ops(package_dict)
                # session.write_transaction(analyse_dependencies, package_dict)  # 分析每个包的依赖关系
        print("finished " + json_name)